package com.learning.spring.aop.aspectj.annotation.advice.advice;

import com.learning.spring.aop.aspectj.annotation.advice.introduction.MonitorAble;
import com.learning.spring.aop.aspectj.annotation.advice.introduction.MonitorAbleImpl;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.DeclareParents;

/**
 * ClassName: AspectAdvisorAnnotationAdvice
 * Description: 注解实现 Advice
 * Date: 2019/4/21 15:35 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
@Aspect
public class AspectAdvisorAnnotationAdvice {

    /**
     * 注解 ：@Before
     * 前置 Advice 相当于 BeforeAdvice
     */
    @Before("execution(* add(..))")
    public void before() {
        System.out.println("Hello   @Before");
    }

    /**
     * 注解 ：@AfterReturning
     * 后置 Advice 相当于 AfterReturningAdvice
     * returning：将目标对象方法的返回值绑定给增强的方法
     */
    @AfterReturning(value = "execution(* add(..))", returning = "result")
    public void afterReturning(String result) {
        System.out.println("Hello   @AfterReturning " + result);
    }

    /**
     * 注解 ：@Around
     * 环绕 Advice 相当于 MethodInterceptor
     */
    @Around("execution(* add(..))")
    public void around(ProceedingJoinPoint invocation) throws Throwable {
        System.out.println("Hello   @Around  before");
        invocation.proceed();
        System.out.println("Hello   @Around  after");
    }

    /**
     * 注解 ：@AfterThrowing
     * 异常抛出 Advice 相当于 ThrowsAdvice
     * 属性 throwing：将抛出的异常绑定到增强方法中
     */
    @AfterThrowing(value = "execution(* error(..))", throwing = "ex")
    public void afterThrowing(Exception ex) {
        System.out.println("Hello   @AfterThrowing  " + ex);
    }

    /**
     * 注解 ：@After
     * After finally advice，不管是抛出异常还是正常退出，该增强都会被执行。
     * 可以看成是 AfterReturning 和 AfterThrowing 的混合物，一般用来释放资源。
     */
    @After("execution(* add(..))")
    public void after() {
        System.out.println("Hello   @After finally advice");
    }

    /**
     * 注解：@DeclareParents
     * 引介 Advice
     * value: 定义切点，表示在哪个目标类上添加引介
     * defaultImpl：默认接口的实现类
     */
    @DeclareParents(value = "com.learning.spring.aop.aspectj.annotation.advice.service.impl.AopServiceImpl",
            defaultImpl = MonitorAbleImpl.class)
    public MonitorAble monitorable;
}